import json
import logging
from datetime import datetime
from typing import Optional, List, Dict

import pytz
import redis
from redis import ConnectionPool


logger = logging.getLogger(__name__)


class ConversationRedisManager:
    """对话上下文管理器（Redis持久化）"""

    def __init__(self,
                 host: str = "",
                 port: int = 0,
                 db: int = 0,
                 decode_responses: bool = True) -> None:
        """
        初始化redis管理实例

        """
        redis_pool = redis.ConnectionPool(
            host=host,
            port=port,
            db=db,
            decode_responses=decode_responses
        )

        logger.debug(f"Connecting to Redis")
        self.redis = redis.Redis(connection_pool=redis_pool)

    def _get_key(self,
                 user_id: str,
                 session_id: str) -> str:
        """
        :param user_id:str      用户身份的唯一标识符
        :param session_id:str   会话窗口ID
        :return 格式为`chat:{user_id}:{session_id}`的Redis键字符串
        """
        return f"chat:{user_id}:{session_id}"

    def load_history(self,
                     user_id: str,
                     session_id: str,
                     max_turns: int = 5) -> List[Dict]:
        """
        加载自动截断的对话历史(基于对话轮次)

        :param user_id: str      用户身份的唯一标识符
        :param session_id: str   会话窗口ID
        :param max_turns: int    最大保留对话轮次(默认5轮)
        :return: List[Dict]      截断后的对话历史,每条记录包含role/content/timestamp
        """
        max_turns = int(max_turns)
        if max_turns < 0:
            max_turns = -max_turns
        if max_turns:
            try:
                history = self.redis.lrange(self._get_key(user_id, session_id), 0, -1)
                return [json.loads(msg) for msg in history][-max_turns * 2:]
            except redis.RedisError as e:
                print(f"Redis读取失败: {str(e)}")
                return []
        else:
            try:
                history = self.redis.lrange(self._get_key(user_id, session_id), 0, -1)
                return [json.loads(msg) for msg in history]
            except redis.RedisError as e:
                print(f"Redis读取失败: {str(e)}")
                return []

    def save_history(self,
                     user_id: str,
                     session_id: str,
                     role: str,
                     type: str,
                     content: str,
                     expire_time: int = 64000):
        """
        持久化单条对话记录并设置过期时间

        :param user_id: str      用户身份的唯一标识符
        :param session_id: str   会话窗口ID
        :param role: str         消息角色(user/assistant)
        :param type: str         保存消息类型
        :param content: str      消息文本内容
        :param expire_time: int  消息过期时间
        """
        try:
            timezone = pytz.timezone('Asia/Shanghai')
            current_time = datetime.now(timezone)
            msg = json.dumps(
                {"role": role, "content": content, "type": type, "timestamp": current_time.strftime("%Y-%m-%dT%H:%M:%S")},
                ensure_ascii=False)
            self.redis.rpush(self._get_key(user_id, session_id), msg)
            # 设置过期时间（7天）
            self.redis.expire(self._get_key(user_id, session_id), expire_time)
            # 维护user_id
            self.redis.sadd("all_users_list", user_id)
            # 维护单日user_id
            self.redis.sadd(f"{current_time.strftime('%Y-%m-%d')}",
                            f"{{'user_id':{user_id},'session_id':{session_id}}}")
        except redis.RedisError as e:
            print(f"Redis写入失败: {str(e)}")

    def clear_history(self,
                      user_id: str,
                      session_id: str):
        """
        删除指定用户的指定会话的全部对话历史

        :param user_id: str      用户身份的唯一标识符
        :param session_id: str   会话窗口ID
        """
        try:
            self.redis.delete(self._get_key(user_id, session_id))
        except redis.RedisError as e:
            print(f"Redis删除失败: {str(e)}")


def set_redis_pools(para_list:List[Dict]):
    redis_manager_list = []
    try:
        for para in para_list:
            name = para.get("name", "test")
            host = para.get("host", "127.0.0.1")
            port = para.get("port", 6379)
            db = para.get("port", 0)
            decode_responses = para.get("decode_responses", True)

            redis_manager = ConversationRedisManager(host=host, port=port, db=db, decode_responses=decode_responses)
            redis_manager_list.append(dict(name=name, redis_manager=redis_manager))
    except Exception as e:
        print(f"!!!Function:set_redis_pools error:{e}")
    return redis_manager_list
